package com.jnks.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jnks.constant.R;
import com.jnks.constant.enums.ShapeTypeEnum;
import com.jnks.mapper.ManagementBoundaryTMapper;
import com.jnks.mapper.ManagementCoordinateTMapper;
import com.jnks.mapper.ManagementObjMapper;
import com.jnks.pojo.domain.dto.ManagementBoundaryInfo;
import com.jnks.pojo.domain.dto.ManagementObj;
import com.jnks.pojo.domain.vo.ManagementObjAddReq;
import com.jnks.pojo.domain.vo.ManagementObjDelReq;
import com.jnks.pojo.domain.vo.ManagementObjEditReq;
import com.jnks.pojo.entity.ManagementBoundaryTDO;
import com.jnks.pojo.entity.ManagementCoordinateTDO;
import com.jnks.pojo.entity.ManagementObjTDO;
import com.jnks.service.ManagementObjService;
import com.jnks.utils.LocationUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 目标管理表 服务实现类
 * </p>
 *
 * @author Ryo
 * @date 2024/4/23
 */
@Service
@RequiredArgsConstructor
public class ManagementObjServiceImpl extends ServiceImpl<ManagementObjMapper, ManagementObjTDO> implements ManagementObjService {

    private final ManagementObjMapper managementObjMapper;
    private final ManagementBoundaryTMapper boundaryTMapper;
    private final ManagementCoordinateTMapper coordinateTMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public R addManagementObj(ManagementObjAddReq req) {

//        List<ManagementObjTDO> managementObjTDOS = managementObjMapper.selectList(new LambdaQueryWrapper<ManagementObjTDO>()
//                .eq(ManagementObjTDO::getStatus, 1));
//        if (!Objects.isNull(managementObjTDOS)){
//            R.error(null,"请勿重复添加");
//        }

        ManagementObjTDO managementObjDO = new ManagementObjTDO();
        BeanUtils.copyProperties(req, managementObjDO);

        managementObjDO.setCreateTime(new Date());
//        managementObjDO.setShowFlag((Objects.isNull(req.getShowFlag()) || req.getShowFlag() == 0) ? CommonStatusEnum.DISABLE.getIntCode() : CommonStatusEnum.ENABLE.getIntCode());
        // 插入中心点坐标
        List<ManagementBoundaryInfo> managementBoundaryInfos = req.getManagementBoundaryInfos();
        if (!managementBoundaryInfos.isEmpty()) {
            managementObjDO.setLongitude(managementBoundaryInfos.get(0).getLongitude());
            managementObjDO.setLatitude(managementBoundaryInfos.get(0).getLatitude());
        }

        if (managementBoundaryInfos.isEmpty()) {
            return R.error(managementBoundaryInfos, "边界信息不能为空！");
        }
        List<ManagementBoundaryInfo> collect = managementBoundaryInfos.stream().sorted(Comparator.comparing(ManagementBoundaryInfo::getLimitFlyType)).collect(Collectors.toList());
        if (collect.get(0).getShape().equals(ShapeTypeEnum.POLYGON.getCode())) {
            List<ManagementCoordinateTDO> managementCoordinateTDOS = collect.get(0).getManagementCoordinateTDOS();
            double maxDistance = Double.MIN_VALUE;
            for (ManagementCoordinateTDO managementCoordinateTDO : managementCoordinateTDOS) {
                String latitude = managementCoordinateTDO.getLatitude();
                String longitude = managementCoordinateTDO.getLongitude();
                double distance = LocationUtils.getDistance(Double.parseDouble(latitude), Double.parseDouble(longitude),
                        Double.parseDouble(managementObjDO.getLatitude()), Double.parseDouble(managementObjDO.getLongitude()));
                if (maxDistance < distance) maxDistance = distance;
            }
            managementObjDO.setCenterToBorderDistance(maxDistance);
        } else {
            managementObjDO.setCenterToBorderDistance(collect.get(0).getRadius());
        }

        managementObjDO.setCreateTime(new Date());
        managementObjMapper.insert(managementObjDO);
        saveConfig(managementBoundaryInfos, managementObjDO);

        return R.data(managementObjDO.getId());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public R editManagementObj(ManagementObjEditReq req) {
        ManagementObjTDO managementObjDO = new ManagementObjTDO();
        BeanUtils.copyProperties(req, managementObjDO);

//        managementObjDO.setShowFlag(Objects.equals(req.getShowFlag(), 1) && !Objects.equals(req.getStatusType(), -1) ? CommonStatusEnum.ENABLE.getIntCode() : CommonStatusEnum.DISABLE.getIntCode());
//        managementObjDO.setStatus(Objects.equals(req.getStatusType(), -1) ? "-1" : "1");
        managementObjDO.setUpdateTime(new Date());
        // 插入中心点坐标
            List<ManagementBoundaryInfo> managementBoundaryInfos = req.getManagementBoundaryInfos();
            if (!managementBoundaryInfos.isEmpty()) {
                managementObjDO.setLongitude(managementBoundaryInfos.get(0).getLongitude());
                managementObjDO.setLatitude(managementBoundaryInfos.get(0).getLatitude());
            }
            List<ManagementBoundaryInfo> collect = managementBoundaryInfos.stream().sorted(Comparator.comparing(ManagementBoundaryInfo::getLimitFlyType)).collect(Collectors.toList());
            if (collect.get(0).getShape().equals(ShapeTypeEnum.POLYGON.getCode())) {
                List<ManagementCoordinateTDO> managementCoordinateTDOS = collect.get(0).getManagementCoordinateTDOS();
                double maxDistance = Double.MAX_VALUE;
                for (ManagementCoordinateTDO managementCoordinateTDO : managementCoordinateTDOS) {
                    String latitude = managementCoordinateTDO.getLatitude();
                    String longitude = managementCoordinateTDO.getLongitude();
                    double distance = LocationUtils.getDistance(Double.parseDouble(latitude), Double.parseDouble(longitude),
                            Double.parseDouble(managementObjDO.getLatitude()), Double.parseDouble(managementObjDO.getLongitude()));
                    if (maxDistance > distance) maxDistance = distance;
                }
                managementObjDO.setCenterToBorderDistance(maxDistance);
            } else {
                managementObjDO.setCenterToBorderDistance(collect.get(0).getRadius());
            }

        List<ManagementBoundaryInfo> managementBoundaryInfoss = req.getManagementBoundaryInfos();
        if (managementBoundaryInfoss.isEmpty()) {
            return R.error(managementBoundaryInfoss, "边界信息不能为空！");
        }
        managementObjMapper.updateById(managementObjDO);
        List<ManagementBoundaryTDO> managementBoundaryTDOS = boundaryTMapper.selectList(new LambdaQueryWrapper<ManagementBoundaryTDO>()
                .eq(ManagementBoundaryTDO::getTargetId, req.getId()));
        if (!managementBoundaryTDOS.isEmpty()) {
            boundaryTMapper.delete(new LambdaQueryWrapper<ManagementBoundaryTDO>()
                    .eq(ManagementBoundaryTDO::getTargetId, req.getId()));
            coordinateTMapper.delete(new LambdaQueryWrapper<ManagementCoordinateTDO>()
                    .eq(ManagementCoordinateTDO::getTargetId, req.getId()));

        }
        saveConfig(managementBoundaryInfos, managementObjDO);

        return R.data(managementObjDO.getId());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public R<Integer> delManagementObj(ManagementObjDelReq req) {
        ManagementObjTDO managementObjDO = managementObjMapper.selectOne(new LambdaQueryWrapper<ManagementObjTDO>()
                .eq(ManagementObjTDO::getId, req.getId()));
        if (Objects.nonNull(managementObjDO)) {
            BeanUtils.copyProperties(req, managementObjDO);
            managementObjDO.setUpdateTime(new Date());
            managementObjDO.setStatus(req.getStatus());
            managementObjMapper.updateById(managementObjDO);
        } else {
            R.error(managementObjDO.getId(), "该目标信息不存在！！！");
        }
        return R.data(managementObjDO.getId());
    }

    @Override
    public List<ManagementObj> selectCoordinateById() {
        List<ManagementBoundaryInfo> managementBoundaryTDOS = new ArrayList<>();

        return managementObjMapper.selectList(new LambdaQueryWrapper<ManagementObjTDO>()
                .eq(ManagementObjTDO::getStatus, 1)).stream().map(managementObjDO -> {
            ManagementObj managementObj = new ManagementObj();
            BeanUtils.copyProperties(managementObjDO, managementObj);
            List<ManagementBoundaryTDO> boundaryTDOS = boundaryTMapper.selectList(new LambdaQueryWrapper<ManagementBoundaryTDO>()
                    .eq(ManagementBoundaryTDO::getTargetId, managementObj.getId()));
            boundaryTDOS.forEach(managementBoundaryTDO -> {
                ManagementBoundaryInfo managementBoundaryInfo = new ManagementBoundaryInfo();
                BeanUtils.copyProperties(managementBoundaryTDO, managementBoundaryInfo);
                List<ManagementCoordinateTDO> coordinateTDOS = coordinateTMapper.selectList(new LambdaQueryWrapper<ManagementCoordinateTDO>()
                        .eq(ManagementCoordinateTDO::getPid, managementBoundaryInfo.getId()));
                managementBoundaryInfo.setManagementCoordinateTDOS(coordinateTDOS);
                managementBoundaryTDOS.add(managementBoundaryInfo);
            });
            managementObj.setManagementBoundaryInfos(managementBoundaryTDOS);

            return managementObj;
        }).collect(Collectors.toList());
    }

    private void saveConfig(List<ManagementBoundaryInfo> managementBoundaryInfos, ManagementObjTDO managementObjDO) {
        managementBoundaryInfos.forEach(managementBoundaryInfo -> {
            ManagementBoundaryTDO managementBoundaryTDO = new ManagementBoundaryTDO();
            BeanUtils.copyProperties(managementBoundaryInfo, managementBoundaryTDO);
            managementBoundaryTDO.setTargetId(managementObjDO.getId());
            managementBoundaryTDO.setUpdateTime(new Date());
            boundaryTMapper.insert(managementBoundaryTDO);
            //插入三级防御圈
            ManagementBoundaryInfo managementBoundary = new ManagementBoundaryInfo();
            BeanUtils.copyProperties(managementBoundaryInfo, managementBoundary);
            List<ManagementCoordinateTDO> managementCoordinateTDOS = managementBoundary.getManagementCoordinateTDOS();
            if (ShapeTypeEnum.POLYGON.getCode().equals(managementBoundary.getShape())) {
                managementCoordinateTDOS.forEach(managementCoordinateTDO -> {
                    ManagementCoordinateTDO managementCoordinate = new ManagementCoordinateTDO();
                    BeanUtils.copyProperties(managementCoordinateTDO, managementCoordinate);
                    managementCoordinate.setPid(managementBoundaryTDO.getId());
                    managementCoordinate.setTargetId(managementObjDO.getId());
                    managementCoordinate.setUpdateTime(new Date());
                    coordinateTMapper.insert(managementCoordinate);
                });
            }
        });
    }

}
